
import  wx
import  wx.grid as gridlib

import middleman

#---------------------------------------------------------------------------


#---------------------------------------------------------------------------

class CustomDataTable(gridlib.PyGridTableBase):
    def __init__(self, log):
        gridlib.PyGridTableBase.__init__(self)
        self.log = log

        self.colLabels = [
            '1',
            '2',
            '3', 
            '4',
            '5',
            '6',
            '7',
            '8',
            '9',
            '10',
            '11']

        self.dataTypes = [gridlib.GRID_VALUE_NUMBER, # cash held
                          gridlib.GRID_VALUE_NUMBER, # tins held
                          gridlib.GRID_VALUE_STRING, # buying phase
                          gridlib.GRID_VALUE_NUMBER, # tins wanted
                          gridlib.GRID_VALUE_NUMBER, # offer per tin 
                          gridlib.GRID_VALUE_NUMBER + ':0,9', # market seed available
                          gridlib.GRID_VALUE_NUMBER, # available tins
                          gridlib.GRID_VALUE_NUMBER, # tins bought
                          gridlib.GRID_VALUE_NUMBER, # cash held
                          gridlib.GRID_VALUE_NUMBER, # tins held
                          gridlib.GRID_VALUE_STRING, # selling phase
                          gridlib.GRID_VALUE_NUMBER, # tins offered
                          gridlib.GRID_VALUE_NUMBER + ':1,10', # price per tin
                          gridlib.GRID_VALUE_NUMBER + ':0,9', # market seed demand
                          gridlib.GRID_VALUE_NUMBER, # tins demanded
                          gridlib.GRID_VALUE_NUMBER] # tins sold

        self.fontStandard = ["BLACK", "Georgia", 14]
        self.fontSeed = ["DARK OLIVE GREEN", "Georgia", 14] 
        self.fontEdit = ["FIREBRICK", "Georgia", 14]   

        self.rowLabels = [
            ['Cash Held',self.fontStandard],
            ['Tins Held',self.fontStandard],
            ['Buying Phase',self.fontStandard],
            ['Tins Wanted',self.fontEdit],
            ['Offer/Tin',self.fontEdit],
            ['Market Seed',self.fontSeed],
            ['Available Tins',self.fontStandard],
            ['Tins Bought',self.fontStandard],
            ['Cash Held',self.fontStandard],
            ['Tins Held',self.fontStandard],
            ['Selling Phase',self.fontStandard],
            ['Tins Offered',self.fontEdit],
            ['Price/Tin',self.fontEdit],
            ['Market Seed',self.fontSeed],
            ['Tins Demanded',self.fontStandard],
            ['Tins Sold',self.fontStandard]]

        
               

        midgrid = middleman.Grid()

        midgrid.grid.cash_held.cells.extend([1,2,3,4,5,6,7,8,9,10,11])
        midgrid.grid.tins_held.cells.extend([1,2,3,4,5,6,7,8,9,10,11])
        midgrid.grid.buying_tins_wanted.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_offer_per_tin.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_market_seed.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_available_tins.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_tins_bought.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_cash_held.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.buying_tins_held.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.selling_tins_offered.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.selling_price_per_tin.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.selling_market_seed.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.selling_tins_demanded.cells.extend([1,2,3,4,5,6,7,8,9,10])
        midgrid.grid.selling_tins_sold.cells.extend([1,2,3,4,5,6,7,8,9,10])

       


        self.data = [
            midgrid.grid.cash_held.cells,
            midgrid.grid.tins_held.cells,
            [None,None,None,None,None,None,None,None,None,None,None],
            midgrid.grid.buying_tins_wanted.cells,
            midgrid.grid.buying_offer_per_tin.cells,
            midgrid.grid.buying_market_seed.cells,
            midgrid.grid.buying_available_tins.cells,
            midgrid.grid.buying_tins_bought.cells,
            midgrid.grid.buying_cash_held.cells,
            midgrid.grid.buying_tins_held.cells,
            [None,None,None,None,None,None,None,None,None,None,None],
            midgrid.grid.selling_tins_offered.cells,
            midgrid.grid.selling_price_per_tin.cells,
            midgrid.grid.selling_market_seed.cells,
            midgrid.grid.selling_tins_demanded.cells,
            midgrid.grid.selling_tins_sold.cells           
            ]


    #--------------------------------------------------
    # required methods for the wxPyGridTableBase interface

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data[0])

    def IsEmptyCell(self, row, col):
        try:
            return not self.data[row][col]
        except IndexError:
            return True

    # Get/Set values in the table.  The Python version of these
    # methods can handle any data-type, (as long as the Editor and
    # Renderer understands the type too,) not just strings as in the
    # C++ version.
    def GetValue(self, row, col):
        try:
            return self.data[row][col]
        except IndexError:
            return ''

    def SetValue(self, row, col, value):
        def innerSetValue(row, col, value):
            try:
                self.data[row][col] = value
            except IndexError:
                # add a new row
                self.data.append([''] * self.GetNumberCols())
                innerSetValue(row, col, value)

                # tell the grid we've added a row
                msg = gridlib.GridTableMessage(self,            # The table
                        gridlib.GRIDTABLE_NOTIFY_ROWS_APPENDED, # what we did to it
                        1                                       # how many
                        )

                self.GetView().ProcessTableMessage(msg)
        innerSetValue(row, col, value) 

    #--------------------------------------------------
    # Some optional methods

    # Called when the grid needs to display labels
    def GetColLabelValue(self, col):
        return self.colLabels[col]

    def GetRowLabelValue(self, row):
        return self.rowLabels[row][0]

    # Called to determine the kind of editor/renderer to use by
    # default, doesn't necessarily have to be the same type used
    # natively by the editor/renderer if they know how to convert.
    def GetTypeName(self, row, col):
        return self.dataTypes[row]

    # Called to determine how the data can be fetched and stored by the
    # editor and renderer.  This allows you to enforce some type-safety
    # in the grid.
    def CanGetValueAs(self, row, col, typeName):
        rowType = self.dataTypes[row].split(':')[0]
        if typeName == rowType:
            return True
        else:
            return False

    def CanSetValueAs(self, row, col, typeName):
        return self.CanGetValueAs(row, col, typeName)   




class MegaFontRenderer(gridlib.PyGridCellRenderer):
    def __init__(self, table, color="blue", font="ARIAL", fontsize=8):
        """Render data in the specified color and font and fontsize"""
        gridlib.PyGridCellRenderer.__init__(self)
        self.table = table
        self.color = color
        self.font = wx.Font(fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, font)
        self.selectedBrush = wx.Brush("blue", wx.SOLID)
        self.normalBrush = wx.Brush(wx.WHITE, wx.SOLID)
        self.colSize = None
        self.rowSize = 50

    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        # Here we draw text in a grid cell using various fonts
        # and colors.  We have to set the clipping region on
        # the grid's DC, otherwise the text will spill over
        # to the next cell
        dc.SetClippingRect(rect)

        # clear the background
        dc.SetBackgroundMode(wx.SOLID)
        
        if isSelected:
            dc.SetBrush(wx.Brush(wx.BLUE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.BLUE, 1, wx.SOLID))
        else:
            dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID))
            dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID))
        dc.DrawRectangleRect(rect)

        text = str(self.table.GetValue(row, col))
        dc.SetBackgroundMode(wx.SOLID)

        # change the text background based on whether the grid is selected
        # or not
        if isSelected:
            dc.SetBrush(self.selectedBrush)
            dc.SetTextBackground("blue")
        else:
            dc.SetBrush(self.normalBrush)
            dc.SetTextBackground("white")

        dc.SetTextForeground(self.color)
        dc.SetFont(self.font)
        dc.DrawText(text, rect.x+1, rect.y+1)

        # Okay, now for the advanced class :)
        # Let's add three dots "..."
        # to indicate that that there is more text to be read
        # when the text is larger than the grid cell

        width, height = dc.GetTextExtent(text)
        
        if width > rect.width-2:
            width, height = dc.GetTextExtent("...")
            x = rect.x+1 + rect.width-2 - width
            dc.DrawRectangle(x, rect.y+1, width+1, height)
            dc.DrawText("...", x, rect.y+1)

        dc.DestroyClippingRegion()

#---------------------------------------------------------------------------

class MegaFontRendererFactory:
    def __init__(self, color, font, fontsize):
        """
        (color, font, fontsize) -> set of a factory to generate
        renderers when called.
        func = MegaFontRenderFactory(color, font, fontsize)
        renderer = func(table)
        """
        self.color = color
        self.font = font
        self.fontsize = fontsize

    def __call__(self, table):
        return MegaFontRenderer(table, self.color, self.font, self.fontsize)



#---------------------------------------------------------------------------        

class CustTableGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        table = CustomDataTable(log)

        # The second parameter means that the grid is to take ownership of the
        # table and will destroy it when done.  Otherwise you would need to keep
        # a reference to it and call it's Destroy method later.
        self.SetTable(table, True)

        #self.SetRowLabelSize(0)
        self.SetMargins(10,10)
        self.AutoSizeColumns(True)

        gridlib.EVT_GRID_CELL_LEFT_DCLICK(self, self.OnLeftDClick)

        row = 0
        for rowLabel in table.rowLabels:
            attr = gridlib.GridCellAttr()
            renderer = MegaFontRendererFactory(table.rowLabels[row][1][0],table.rowLabels[row][1][1],table.rowLabels[row][1][2])(table)
            if renderer.colSize:
                self.SetDefaultColSize(renderer.colSize)
            if renderer.rowSize:
                self.SetRowSize(row, renderer.rowSize)
            attr.SetRenderer(renderer)
            self.SetRowAttr(row, attr)
            row += 1


    # I do this because I don't like the default behaviour of not starting the
    # cell editor on double clicks, but only a second click.
    def OnLeftDClick(self, evt):
        if self.CanEnableCellControl():
            self.EnableCellEditControl()

#---------------------------------------------------------------------------



#---------------------------------------------------------------------------

class TestFrame(wx.Frame):
    def __init__(self, parent, log):

        wx.Frame.__init__(
            self, parent, -1, "Middleman", size=(640,480)
            )

        p = wx.Panel(self, -1, style=0)

        grid = CustTableGrid(p, log)

        b = wx.Button(p, -1, "Another Control...")
        b.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)
        b.Bind(wx.EVT_SET_FOCUS, self.OnButtonFocus)

        bs = wx.BoxSizer(wx.VERTICAL)
        bs.Add(grid, 1, wx.GROW|wx.ALL, 5)
        bs.Add(b)
        p.SetSizer(bs)

    def OnButton(self, evt):
        print "button selected"

    def OnButtonFocus(self, evt):
        print "button focus"


#---------------------------------------------------------------------------

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()


#---------------------------------------------------------------------------
